package com.sec.etech.ism.service.impl;

import cn.hutool.core.util.StrUtil;
import cn.hutool.http.HttpUtil;
import com.alibaba.fastjson.JSONObject;
import com.sec.etech.ism.service.MaterialNoLogService;
import com.sec.etech.ism.model.IsmAppSetting;
import com.sec.etech.ism.model.IsmServiceDef;
import com.sec.etech.ism.service.*;
import com.sec.etech.ism.util.SapSignatureUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.MapUtils;
import org.openbpm.base.core.util.StringUtil;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Slf4j
@Service
public class IsmUpdateMaterialNoServiceImpl implements IsmMethodService {
    @Resource
    JdbcTemplate jdbcTemplate;
    @Resource
    IsmAppSettingService ismAppSettingService;
    @Resource
    IsmTaskService ismTaskService;
    @Resource
    IsmServiceDefService ismServiceDefService;
    @Resource
    IsmTaskLogService ismTaskLogService;
    @Resource
    MaterialNoLogService materialNoLogService;
    @Resource
    IsmCommonService ismCommonService;

    public IsmUpdateMaterialNoServiceImpl(){}

    @Override
    public JSONObject call(String sysCode, String serviceCode, JSONObject businessParams) throws Exception{
        JSONObject result = new JSONObject();
        String msg = this.updatePartsMaterialNo(sysCode, serviceCode, businessParams);
        result.put("flag", msg);
        result.put("msg", msg);
        return result;
    }

    /**
     * 调用SAP接口批量更新零件/毛坯物料号
     * @param sysCode
     * @param serviceCode
     * @param busObj
     * @return
     */
    private String updatePartsMaterialNo(String sysCode, String serviceCode, JSONObject busObj) {
        Map<String, String> logMap = new HashMap<>(5);
        //服务信息
        IsmServiceDef serviceDef = ismServiceDefService.getByCode(serviceCode);
        try{
            //调用的应用信息
            IsmAppSetting appSetting = ismAppSettingService.getByCode(sysCode);
            String url = ismCommonService.getSapPreUrl(appSetting.getAppAddress(), appSetting.getAppConfig()) + "/ZBAPI_MATERIAL_SAVEDATA_LIST";
            Integer busType = busObj.getInteger("busType");//2-零件，3-毛坯物料号
            List<Map<String, Object>> partsList = null;
            StringBuffer sqlBuf = new StringBuffer()
                    .append("SELECT distinct t1.partsid,t1.partsnum,t1.partsname,t1.weight,t1.tips,t1.cooperation_num,t1.billet_size,")
                    .append("  t1.parts_incision,t1.chuck_quantity,t1.billet_specifications,t1.billet_max_size,t1.insurance_amount,")
                    .append("  t1.parts_section_length,t1.unit_parts_gross_weight,t1.unit_parts_quota,t1.material_SAPnum,")
                    .append("  t1.route1,t1.route2,t1.route3,t1.route4,t1.route5,t1.route6,t1.route7,t1.route8,t1.route9,t1.route10,")
                    .append("  t1.route11,t1.route12,t1.route13,t1.parts_SAPnum,t1.billet_SAPnum,t2.metalNumname,t3.heatname heatTreatmentname,")
                    .append("  t4.`name` route0name,t5.`name` attributename,t6.`name` metalshortname,t7.remark ")
                    .append("FROM prod_parts t1 left join sam_mmd_metalNum t2 on t1.metalNumid=t2.metalNumid")
                    .append("  left join prod_parts_z_heat t3 on t1.heatTreatmentid=t3.heatid")
                    .append("  left join prod_parts_z_route0 t4 on t1.route0=t4.route0id")
                    .append("  left join prod_parts_z_attribute t5 on t1.partsAttributeid=t5.partsAttributeid")
                    .append("  left join prod_parts_z_metalshortname t6 on t1.metalShortNameid=t6.metalShortNameid")
                    .append("  left join proj_component_route t7 on t1.original_componentid=t7.componentid and t1.partsid=t7.partsid ")
                    .append("where t1.drawing_logo!=1 and t1.parts_SAPnum is not null and t1.parts_SAPnum!='' ");
            if(busObj.containsKey("componentid") && busObj.getLong("componentid")>0) {//单个部套（修改单、管理员操作）
                sqlBuf.append(" and t1.active=1 and t1.original_componentid=?");
                partsList = jdbcTemplate.queryForList(sqlBuf.toString(), busObj.getString("componentid"));
            }else if(StringUtil.isNotEmpty(busObj.getString("componentids"))) {
                sqlBuf.append(" and t1.active=1 and t1.original_componentid in ({})");
                partsList = jdbcTemplate.queryForList(StrUtil.format(sqlBuf.toString(), busObj.getString("componentids")));
            }else if(busObj.containsKey("partsid") && busObj.getLong("partsid")>0) {
                sqlBuf.append(" and t1.partsid=?");
                partsList = jdbcTemplate.queryForList(sqlBuf.toString(), busObj.getString("partsid"));
            }else if(StringUtil.isNotEmpty(busObj.getString("partsids"))) {
                sqlBuf.append(" and t1.partsid in ({})");
                partsList = jdbcTemplate.queryForList(StrUtil.format(sqlBuf.toString(), busObj.getString("partsids")));
            }
            if(partsList==null || partsList.size()==0){
                return "success";
            }
            //获取数据字典路线1--13配置表
            List<Map<String, Object>> routeXList = jdbcTemplate.queryForList("select routexid,`name` from prod_parts_z_routex");
            Map<String, String> routeXMap = new HashMap<>();
            for(Map<String, Object> map:routeXList){
                routeXMap.put(map.get("routexid").toString(), map.get("name").toString());
            }
            JSONObject sapParams = new JSONObject();
            List<JSONObject> zHeadList = new ArrayList<>();
            List<JSONObject> zClientList = new ArrayList<>();
            List<JSONObject> zClientXList = new ArrayList<>();
            List<JSONObject> zPlantList = new ArrayList<>();
            List<JSONObject> zPlantXList = new ArrayList<>();
            List<JSONObject> zPLMSJ2List = new ArrayList<>();
            List<JSONObject> zPLMSJX2List = new ArrayList<>();
            List<JSONObject> zPLMGY2List = new ArrayList<>();
            List<JSONObject> zPLMCL2List = new ArrayList<>();
            List<JSONObject> zUnitSureList = new ArrayList<>();
            List<JSONObject> zUnitSureXList = new ArrayList<>();
            List<JSONObject> zMDList = new ArrayList<>();
            Map<String, Map<String, Object>> sapNumMap = new HashMap<>();
            //更新物料号
            this.getSapParams(zHeadList, zClientList, zClientXList, zPlantList, zPlantXList, zPLMSJ2List, zPLMSJX2List,
                    zPLMGY2List, zPLMCL2List, zUnitSureList, zUnitSureXList, zMDList, routeXMap, sapNumMap, partsList, busType);
            if(busType==2) {//零件额外更新毛坯物料号
                this.getSapParams(zHeadList, zClientList, zClientXList, zPlantList, zPlantXList, zPLMSJ2List, zPLMSJX2List,
                        zPLMGY2List, zPLMCL2List, zUnitSureList, zUnitSureXList, zMDList, routeXMap, sapNumMap, partsList, 3);
            }
            partsList.clear();
            sapParams.put("ZHEADDATA", zHeadList);
            sapParams.put("ZCLIENTDATA", zClientList);
            sapParams.put("ZCLIENTDATAX", zClientXList);
            sapParams.put("ZPLANTDATA", zPlantList);
            sapParams.put("ZPLANTDATAX", zPlantXList);
            sapParams.put("ZPLM_ROUTING_QUOTATION_SJ2", zPLMSJ2List);
            sapParams.put("ZPLM_ROUTING_QUOTATION_SJX2", zPLMSJX2List);
            sapParams.put("ZPLM_ROUTING_QUOTATION_GY2", zPLMGY2List);
            sapParams.put("ZPLM_ROUTING_QUOTATION_CL2", zPLMCL2List);
            sapParams.put("ZUNITSOFMEASURE", zUnitSureList);
            sapParams.put("ZUNITSOFMEASUREX", zUnitSureXList);
            sapParams.put("ZMATERIALDESCRIPTION", zMDList);

            JSONObject dataObj = this.checkSapResult(url, sapParams, serviceDef, appSetting.getAppKey2(),
                    null, busObj.toJSONString(), sysCode, "ZBAPI_MATERIAL_SAVEDATA_LIST", logMap);
            sapParams.clear();
            Map<String, String> sapReturnMap = new HashMap<>();
            if(dataObj!=null && dataObj.containsKey("RETURNS")){
                List<JSONObject> returnList = (List<JSONObject>) dataObj.get("RETURNS");
                if(returnList!=null && returnList.size()>0) {
                    for(JSONObject object : returnList){
                        String type = object.getString("TYPE");
                        String materialNo = object.getString("ID");
                        sapReturnMap.put(materialNo, type);
                    }
                }
            }
            for(Map.Entry<String, Map<String, Object>> entry:sapNumMap.entrySet()){
                String materialNo = entry.getKey();
                String type = sapReturnMap.get(materialNo);
                Integer result = null;
                if(StringUtil.isEmpty(type) && !"E".equals(type) && !"A".equals(type)) {
                    result = 1;
                }else {
                    result = 0;
                }
                Map<String, Object> busMap = entry.getValue();
                Integer busTypeTemp = 2;
                if(!StringUtils.isEmpty(materialNo) && !materialNo.endsWith("0") && materialNo.length() != 8){//毛坯
                    busTypeTemp = 3;
                }
                //保存或者更新物料号记录表
                materialNoLogService.saveOrUpdateByUpdate(Long.parseLong(busMap.get("partsid").toString()), busTypeTemp,
                        busObj.toJSONString(), materialNo, result, busMap.get("partsnum").toString(), busMap.get("partsname").toString());
            }
            if(dataObj==null){
                return "批量更新零件/毛坯物料号接口异常，请联系管理员处理！";
            }else if(StringUtil.isEmpty(dataObj.getString("message"))){
                return "success";
            }else {
                return dataObj.getString("message");
            }
        }catch (Exception e){
            e.printStackTrace();
            log.error("批量更新零件/毛坯物料号接口异常。serviceDef.getCode()={}，serviceDef.getName()={}，logMap={}",
                    serviceDef.getCode(), serviceDef.getName(), logMap);
            return "批量更新零件/毛坯物料号接口异常，请联系管理员处理！";
        }
    }
    //组装物料号信息
    private void getSapParams(List<JSONObject> zHeadList, List<JSONObject> zClientList, List<JSONObject> zClientXList,
                              List<JSONObject> zPlantList, List<JSONObject> zPlantXList, List<JSONObject> zPLMSJ2List,
                              List<JSONObject> zPLMSJX2List, List<JSONObject> zPLMGY2List, List<JSONObject> zPLMCL2List,
                              List<JSONObject> zUnitSureList,List<JSONObject> zUnitSureXList, List<JSONObject> zMDList,
                              Map<String, String> routeXMap, Map<String, Map<String, Object>> sapNumMap,
                              List<Map<String, Object>> partsList, Integer busType) {

        for(Map<String, Object> map:partsList){
            String sAPNum = null;
            if(busType==2){//零件物料号
                sAPNum = map.get("parts_SAPnum")!=null ? map.get("parts_SAPnum").toString() : "";
            }else if(busType==3){//毛坯物料号
                sAPNum = map.get("billet_SAPnum")!=null ? map.get("billet_SAPnum").toString() : "";
                if(StringUtil.isEmpty(sAPNum)){
                    continue;
                }
            }
            sapNumMap.put(sAPNum, map);

            JSONObject zHeadObj = new JSONObject(2);
            zHeadObj.put("MATERIAL", sAPNum);//物料号
            zHeadObj.put("STORAGE_VIEW", "X");
            zHeadList.add(zHeadObj);

            JSONObject zClientObj = new JSONObject(4);
            zClientObj.put("MATERIAL", sAPNum);//物料号
            zClientObj.put("DIVISION", "50");
            if(busType==2) {//零件
                BigDecimal weight = map.get("weight")!=null ? new BigDecimal(map.get("weight").toString()) : BigDecimal.ZERO;
                zClientObj.put("NET_WEIGHT", weight.setScale(3, BigDecimal.ROUND_HALF_UP));//净重
            }else if(busType==3){//毛坯
                BigDecimal weight = map.get("unit_parts_gross_weight")!=null ? new BigDecimal(map.get("unit_parts_gross_weight").toString()) : BigDecimal.ZERO;
                zClientObj.put("NET_WEIGHT", weight.setScale(3, BigDecimal.ROUND_HALF_UP));//零件毛重
            }
            zClientObj.put("UNIT_OF_WT", "KG");//单位
            zClientList.add(zClientObj);

            JSONObject zClientXObj = new JSONObject(3);
            zClientXObj.put("MATERIAL", sAPNum);//物料号
            zClientXObj.put("NET_WEIGHT", "X");
            zClientXObj.put("UNIT_OF_WT", "X");
            zClientXList.add(zClientXObj);

            JSONObject zPlantObj = new JSONObject(2);
            zPlantObj.put("MATERIAL", sAPNum);//物料号
            zPlantObj.put("PLANT", "1303");
            zPlantList.add(zPlantObj);

            JSONObject zPlantXObj = new JSONObject(2);
            zPlantXObj.put("MATERIAL", sAPNum);//物料号
            zPlantXObj.put("PLANT", "1303");
            zPlantXList.add(zPlantXObj);

            JSONObject zPLMSJ2Obj = new JSONObject(4);
            zPLMSJ2Obj.put("MATERIAL", sAPNum);//物料号
            zPLMSJ2Obj.put("ZGJCC", MapUtils.getString(map, "tips", ""));//零件备注
            zPLMSJ2Obj.put("ZCLPH", MapUtils.getString(map, "metalNumname", ""));//材料牌号
            zPLMSJ2Obj.put("ZRCZT", MapUtils.getString(map, "heatTreatmentname", ""));///热处理状态
            zPLMSJ2List.add(zPLMSJ2Obj);

            JSONObject zPLMSJX2Obj = new JSONObject(4);
            zPLMSJX2Obj.put("MATERIAL", sAPNum);//物料号
            zPLMSJX2Obj.put("ZGJCC", "X");//零件备注
            zPLMSJX2Obj.put("ZCLPH", "X");//材料牌号
            zPLMSJX2Obj.put("ZRCZT", "X");///热处理状态
            zPLMSJX2List.add(zPLMSJX2Obj);

            JSONObject zPLMGY2Obj = new JSONObject();
            zPLMGY2Obj.put("MATERIAL", sAPNum);//物料号
            zPLMGY2Obj.put("ZZCGLX", map.get("route0name"));//路线0
            zPLMGY2Obj.put("STEP1", this.getRouteXCode(routeXMap, map.get("route1")));//路线1
            zPLMGY2Obj.put("STEP2", this.getRouteXCode(routeXMap, map.get("route2")));//路线2
            zPLMGY2Obj.put("STEP3", this.getRouteXCode(routeXMap, map.get("route3")));//路线3
            zPLMGY2Obj.put("STEP4", this.getRouteXCode(routeXMap, map.get("route4")));//路线4
            zPLMGY2Obj.put("STEP5", this.getRouteXCode(routeXMap, map.get("route5")));//路线5
            zPLMGY2Obj.put("STEP6", this.getRouteXCode(routeXMap, map.get("route6")));//路线6
            zPLMGY2Obj.put("STEP7", this.getRouteXCode(routeXMap, map.get("route7")));//路线7
            zPLMGY2Obj.put("STEP8", this.getRouteXCode(routeXMap, map.get("route8")));//路线8
            zPLMGY2Obj.put("STEP9", this.getRouteXCode(routeXMap, map.get("route9")));//路线9
            zPLMGY2Obj.put("STEP10", this.getRouteXCode(routeXMap, map.get("route10")));//路线10
            zPLMGY2Obj.put("STEP11", this.getRouteXCode(routeXMap, map.get("route11")));//路线11
            zPLMGY2Obj.put("STEP12", this.getRouteXCode(routeXMap, map.get("route12")));//路线12
            zPLMGY2Obj.put("STEP13", this.getRouteXCode(routeXMap, map.get("route13")));//路线13
            zPLMGY2Obj.put("ZZLJSX", MapUtils.getString(map,"attributename",""));//零件属性
            //毛坯状态
            if(busType==2 && StringUtil.isNotEmpty(map.get("billet_SAPnum"))) {
                String billetSAPnum = map.get("billet_SAPnum").toString();
                if(billetSAPnum.endsWith("D5")){
                    zPLMGY2Obj.put("ZZMPZT", "D5");//毛坯状态
                }else {
                    zPLMGY2Obj.put("ZZMPZT", billetSAPnum.substring(billetSAPnum.length()-1));//毛坯状态
                }
            }
            zPLMGY2Obj.put("ZZBZ", MapUtils.getString(map,"remark",""));//部套下零件备注
            zPLMGY2List.add(zPLMGY2Obj);

            JSONObject zPLMCL2Obj = new JSONObject();
            zPLMCL2Obj.put("MATERIAL", sAPNum);//物料号
            zPLMCL2Obj.put("COOPAMOUNT", map.get("cooperation_num"));//合制件数
            zPLMCL2Obj.put("STANDARD", map.get("billet_size"));//坯料尺寸
            zPLMCL2Obj.put("PARTCUT", map.get("parts_incision"));//零件切口
            zPLMCL2Obj.put("JIATOU", map.get("chuck_quantity"));//夹头量
            zPLMCL2Obj.put("BDLENGTH", map.get("billet_specifications"));//坯料或外购件规格
            zPLMCL2Obj.put("BULENGTH", map.get("billet_max_size"));//坯料最长合并尺寸
            zPLMCL2Obj.put("INSUAMOUNT", map.get("insurance_amount"));//保险量
            zPLMCL2Obj.put("PARTDLENGTH", map.get("parts_section_length"));//零件断面长度
            zPLMCL2Obj.put("ZZPLMMEINS", "KG");//单位
            BigDecimal quota = map.get("unit_parts_quota")!=null ? new BigDecimal(map.get("unit_parts_quota").toString()) : BigDecimal.ZERO;
            if(busType==2) {//零件
                zPLMCL2Obj.put("ZZLJDE", quota.setScale(3, BigDecimal.ROUND_HALF_UP));//材料消耗定额
            }
            zPLMCL2Obj.put("ZZCLMC",  MapUtils.getString(map,"metalshortname",""));//材料名称
            zPLMCL2Obj.put("ZZYCLDM", map.get("material_SAPnum"));//原材料编码
            zPLMCL2List.add(zPLMCL2Obj);

            JSONObject zUnitSureObj = new JSONObject();
            zUnitSureObj.put("MATERIAL", sAPNum);//物料号
            zUnitSureObj.put("ALT_UNIT", "EA");
            zUnitSureObj.put("NUMERATOR", "1");
            zUnitSureObj.put("DENOMINATR", "1");
            BigDecimal grossWT = null;
            if(busType==2) {//零件毛重
                grossWT = map.get("unit_parts_gross_weight")!=null ? new BigDecimal(map.get("unit_parts_gross_weight").toString()) : BigDecimal.ZERO;
            }else if(busType==3) {//毛坯毛重
                grossWT = map.get("unit_parts_quota")!=null ? new BigDecimal(map.get("unit_parts_quota").toString()) : BigDecimal.ZERO;//材料消耗定额
            }
            zUnitSureObj.put("GROSS_WT", grossWT.setScale(3, BigDecimal.ROUND_HALF_UP));//毛重
            zUnitSureObj.put("UNIT_OF_WT", "KG");
            zUnitSureList.add(zUnitSureObj);

            JSONObject zUnitSureXObj = new JSONObject();
            zUnitSureXObj.put("MATERIAL", sAPNum);//物料号
            zUnitSureXObj.put("ALT_UNIT", "EA");
            zUnitSureXObj.put("NUMERATOR", "X");
            zUnitSureXObj.put("DENOMINATR", "X");
            zUnitSureXObj.put("GROSS_WT", "X");
            zUnitSureXObj.put("UNIT_OF_WT", "X");
            zUnitSureXList.add(zUnitSureXObj);

            JSONObject zMDObj = new JSONObject();
            zMDObj.put("MATERIAL", sAPNum);//物料号
            zMDObj.put("LANGU_ISO", "ZH");
            zMDObj.put("MATL_DESC", map.get("partsnum").toString() + " " + map.get("partsname").toString());
            zMDList.add(zMDObj);
        }
    }
    //检查sap返回结果，获取返回数据
    private JSONObject checkSapResult(String url, JSONObject sapParams, IsmServiceDef serviceDef, String appKey, String businessCode,
                                      String businessParams, String sysCode, String methodName, Map<String, String> logMap) throws Exception{

        JSONObject bodyObj = SapSignatureUtil.buildRequestParams(sapParams, appKey);
        String body = JSONObject.toJSONString(bodyObj);
        int timeout = JSONObject.parseObject(serviceDef.getParams()).getInteger("timeout");
        long startTime = System.currentTimeMillis();
        String result = HttpUtil.post(url, body, timeout*60*1000);
        log.info("SAP系统{}接口耗时：{}ms。", methodName, System.currentTimeMillis() - startTime);
        JSONObject resultObj = JSONObject.parseObject(result);

        JSONObject taskObj = new JSONObject();
        taskObj.put("sysCode", sysCode);
        taskObj.put("serviceCode", serviceDef.getCode());
        taskObj.put("methodName", methodName);
        taskObj.put("businessCode", businessCode);
        taskObj.put("businessParams", businessParams);
        taskObj.put("resultObj", resultObj);
        Long taskId = ismTaskService.checkAndSave(taskObj);
        //保存接口调用日志
        JSONObject logObj = new JSONObject();
        logObj.put("task_id", taskId);
        logObj.put("service_code", serviceDef.getCode());
        logObj.put("service_name", serviceDef.getName());
        logObj.put("method_name", methodName);
        logObj.put("request_url", url);
        logObj.put("input_json", bodyObj);
        logObj.put("output_json", result);
        JSONObject dataObj = resultObj!=null ? resultObj.getJSONObject("data") : null;
        String message = null;
        if(resultObj==null || !resultObj.getBoolean("success")) {
            message = resultObj!=null ? resultObj.getString("message") : "接口无返回数据，请检查接口和网络！";
        }else if(dataObj!=null && StringUtil.isNotEmpty(dataObj.getString("RETURN"))) {
            message = dataObj.getJSONObject("RETURN").getString("MESSAGE");
        }else if(dataObj!=null && StringUtil.isNotEmpty(dataObj.getString("RET"))) {
            message = dataObj.getJSONObject("RET").getString("MESSAGE");
        }
        if(taskId!=null && taskId>0) {
            message = StringUtil.isNotEmpty(message) ? message : "接口返回数据需要人工检查和处理！";
            logObj.put("message", message);
        }
        logMap.put("input", body);
        logMap.put("output", result);
        ismTaskLogService.saveLog(logObj);
        if(dataObj!=null) {
            dataObj.put("message", message);
        }
        return dataObj;
    }

    //根据数据字典获取routeX
    private String getRouteXCode(Map<String, String> routeXMap, Object routeX){
        if(StringUtil.isNotEmpty(routeX)){
            return routeXMap.get(routeX.toString());
        }else {
            return "";
        }
    }
    @Override
    public String methodName(){
        return "updateMaterialNo";
    }
}
